package com.zhixiang.xaec.action.bpmndemo;


import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.impl.json.JsonListConverter;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.zhixiang.core.bpmndemo.MyJsonProcessDefinitionConverter;
import com.zhixiang.core.bpmndemo.MyJsonTaskConverter;
import com.zhixiang.core.command.QueryFilter;
import com.zhixiang.core.entity.TreeObj;
import com.zhixiang.core.web.action.BaseAction;
import com.zhixiang.xaec.service.bpmndemo.WorkflowService;


/**
 * @author gao
 * @since 2017年1月5日
 */
@Controller
@Scope("prototype")
public class WorkflowAction extends BaseAction
{

    private static final long serialVersionUID = -1249358845809373231L;

    private File bpmnFile;

    public File getBpmnFile()
    {
        return bpmnFile;
    }

    public void setBpmnFile(File bpmnFile)
    {
        this.bpmnFile = bpmnFile;
    }

    public String getBpmnFilName()
    {
        return bpmnFilName;
    }

    public void setBpmnFilName(String bpmnFilName)
    {
        this.bpmnFilName = bpmnFilName;
    }

    private String bpmnFilName;

    @Autowired
    private WorkflowService workflowService;

    /**
     * 发布流程
     * 
     * @return
     */
    public void newdeploy()
    {
        // 完成部署
        workflowService.saveNewDeploye(bpmnFile, bpmnFilName);
        outHtmlString("{success:true}");
    }
    //获取流程定义信息列表
    public String listProcessDefinition()
        throws IOException
    {
        QueryFilter localQueryFilter = new QueryFilter(getRequest());
        // 2:查询流程定义的信息，对应表（act_re_procdef）
        List<ProcessDefinition> list = workflowService.findProcessDefinitionList(localQueryFilter);
        setTotalCounts(localQueryFilter.getPagingBean().getTotalItems());
        MyJsonProcessDefinitionConverter jdc = new MyJsonProcessDefinitionConverter();
        JsonListConverter<ProcessDefinition> sc = new JsonListConverter<ProcessDefinition>(jdc);
        String jsonString = sc.toJson(list);
        System.out.println(jsonString);
        Gson gson = new Gson();
        Object obj = gson.fromJson(jsonString, Object.class);
        setResult(obj);
        return SUCCESS;
    }
   //获取流程部署信息列表
    public String listDemploy()
    {
        QueryFilter localQueryFilter = new QueryFilter(getRequest());
        // 1:查询部署对象信息，对应表（act_re_deployment）
        List<Deployment> list = workflowService.findDeploymentList(localQueryFilter);
        setTotalCounts(localQueryFilter.getPagingBean().getTotalItems());
        Gson gson = new Gson();
        // 只能手动转换json,struts返回转json时会调用实现类中的getResources方法，该方法会从栈中找context,但context=null，会保异常
        // 而且自己转json后，list变成字符串，还的再转成对象后，由struts的自动转换再转就不会出现问题了
        Object obj = gson.fromJson(gson.toJson(list), Object.class);
        setResult(obj);
        return SUCCESS;
    }

    /**
     * 删除部署信息
     */
    public String delDeployment()
    {
        // 1：获取部署对象ID
        String deploymentId = getRequest().getParameter("ids");
        // 2：使用部署对象ID，删除流程定义
        workflowService.deleteProcessDefinitionByDeploymentId(deploymentId);
        return SUCCESS;
    }

    /**
     * 查看流程图
     * 
     * @throws Exception
     */
    public void viewImage()
        throws Exception
    {
        // 1：获取页面传递的部署对象ID和资源图片名称
        // 部署对象ID
        String deploymentId = getRequest().getParameter("deploymentId");
        // 资源图片名称
        String imageName = getRequest().getParameter("diagramResourceName");
        // 2：获取资源文件表（act_ge_bytearray）中资源图片输入流InputStream
        InputStream in = workflowService.findImageInputStream(deploymentId, imageName);
        // 3：从response对象获取输出流
        OutputStream out = ServletActionContext.getResponse().getOutputStream();
        // 4：将输入流中的数据读取出来，写到输出流中
        for (int b = -1; (b = in.read()) != -1;)
        {
            out.write(b);
        }
        out.close();
        in.close();
    }
    //将流程定义拼成一个树结构返回
    public String findFlowTree()
    {
        String companyId = "1";
        List<ProcessDefinition> list = workflowService.findProcessDefinitionDistinctByCmpId(companyId);
        List<TreeObj> treelist = new ArrayList<TreeObj>();
        for (ProcessDefinition p : list)
        {
            TreeObj tobj = new TreeObj();
            tobj.setId(p.getKey());
            tobj.setText(p.getName());
            tobj.setLeaf(true);
            treelist.add(tobj);
        }
        outJsonString(JSON.toJSONString(treelist));
        return SUCCESS;
    }
    //解析数据库中保存的xml文件，获取任务节点信息
    public String findTaskByBpmnXML()
        throws IOException
    {
        String processDefinitionKey = getRequest().getParameter("processDefinitionKey");
        if(StringUtils.isNotEmpty(processDefinitionKey)){
            // 根据流程的ID获取流程定义
            ProcessDefinition pd = workflowService.findProcessDefinitionByKey(processDefinitionKey);
            // 根据部署ID和资源名称获取bpmn的xml文件的输入流
            InputStream in = workflowService.findXMLInputStream(pd.getDeploymentId(),
                pd.getResourceName());
            XMLInputFactory xif = XMLInputFactory.newInstance();
            InputStreamReader in2;
            XMLStreamReader xtr;
            try
            {
                // 用二进制的文件流创建字符输入流
                in2 = new InputStreamReader(in, "UTF-8");
                // 创建XML字符输入流
                xtr = xif.createXMLStreamReader(in2);
                // 将XML的字符流转化成BpmnModel
                BpmnModel model = new BpmnXMLConverter().convertToBpmnModel(xtr);
                Collection<FlowElement> flowElements = model.getMainProcess().getFlowElements();
                List<UserTask> userTaskList = new ArrayList<UserTask>();
                for (FlowElement e : flowElements)
                {
                    // System.out.println("flowelement id:" + e.getId() + "  name:" + e.getName() +
                    // "   class:" + e.getClass().toString());
                    if (e instanceof UserTask)
                    {
                        userTaskList.add((UserTask)e);
                    }
                }
                xtr.close();
                in2.close();
                setResult(userTaskList);
            }
            catch (XMLStreamException e)
            {
                e.printStackTrace();
            }
            catch (UnsupportedEncodingException e)
            {
                e.printStackTrace();
            }
            in.close();
        }

        return SUCCESS;
    }
    //根据用户获取待完成任务
    public String listUnfinishedTask(){
        String userId="1";
        QueryFilter localQueryFilter = new QueryFilter(getRequest());
        List <Task>list = workflowService.findUnfinishedTasksByUserId(userId,localQueryFilter);
        List <Task>list2 = workflowService.findUnfinishedTasksByCandidateUser(userId,localQueryFilter); 
        if(list2.size()>0){
            list.addAll(list2);
        }
        setTotalCounts(localQueryFilter.getPagingBean().getTotalItems());
        MyJsonTaskConverter mtc= new MyJsonTaskConverter();
        JsonListConverter<Task> sc = new JsonListConverter<Task>(mtc);
        // 只能手动转换json,struts返回转json时会调用实现类中的getResources方法，该方法会从栈中找context,但context=null，会保异常
        // 而且自己转json后，list变成字符串，还的再转成对象后，由struts的自动转换再转就不会出现问题了
        String jsonString = sc.toJson(list);
        System.out.println(jsonString);
        Gson gson = new Gson();
        Object obj = gson.fromJson(jsonString, Object.class);
        setResult(obj);
        return SUCCESS;
    }
    //获取businessKey
    public String findInfoBeforeAudit(){
        String processInstanceId=getRequest().getParameter("processInstanceId");
        if(StringUtils.isNotEmpty(processInstanceId)){
            ProcessInstance processInstance= workflowService.getProcessInstanceById(processInstanceId);
            setResult(processInstance.getBusinessKey());
        }
        
        return SUCCESS;
    }
    //获取批注信息
    public String listComment(){
        String processInstanceId=getRequest().getParameter("processInstanceId");
        if(StringUtils.isNotEmpty(processInstanceId)){
            List<Comment> list= workflowService.findComentsByInstanceId(processInstanceId);
            setResult(list);
        }
        return SUCCESS;
    }
    /**
     * 当前活动节点的坐标
     */
    public String viewCurrentTaskCoording(){
        //任务ID
        String taskId = getRequest().getParameter("taskId");
      //1：获取任务ID，获取任务对象，使用任务对象获取流程定义ID，查询流程定义对象
        ProcessDefinition pd = workflowService.findProcessDefinitionByTaskId(taskId);
        /**查看当前活动，获取当期活动对应的坐标x,y,width,height，将4个值存放到Map<String,Object>中*/
        Map<String, Object> map = workflowService.findCoordingByTask(taskId);
        map.put("deploymentId", pd.getDeploymentId());
        map.put("diagramResourceName", pd.getDiagramResourceName());
        setResult(map);
        return SUCCESS;
    }
}
